Build option to include AArch32 registers in cpu context
authorSoby Mathew <[email protected]>
Tue, 17 May 2016 13:01:32 +0000 (14:01 +0100)
committerSoby Mathew <[email protected]>
Fri, 3 Jun 2016 09:50:52 +0000 (10:50 +0100)
The system registers that are saved and restored in CPU context include
AArch32 systems registers like SPSR_ABT, SPSR_UND, SPSR_IRQ, SPSR_FIQ,
DACR32_EL2, IFSR32_EL2 and FPEXC32_EL2. Accessing these registers on an
AArch64-only (i.e. on hardware that does not implement AArch32, or at
least not at EL1 and higher ELs) platform leads to an exception. This patch
introduces the build option `CTX_INCLUDE_AARCH32_REGS` to specify whether to
include these AArch32 systems registers in the cpu context or not. By default
this build option is set to 1 to ensure compatibility. AArch64-only platforms
must set it to 0. A runtime check is added in BL1 and BL31 cold boot path to
verify this.

Fixes ARM-software/tf-issues#386

Change-Id: I720cdbd7ed7f7d8516635a2ec80d025f478b95ee

Makefile
bl1/bl1_context_mgmt.c
bl31/bl31_main.c
common/aarch64/context.S
docs/user-guide.md
include/common/context.h

index b1560a2ba881d0962729a366bbbd97ec2c989e62..ccb0abc341e13206158c41b6f533b4981f77e3c2 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -62,6 +62,9 @@ NS_TIMER_SWITCH                       := 0
 RESET_TO_BL31                  := 0
 # Include FP registers in cpu context
 CTX_INCLUDE_FPREGS             := 0
+# Build flag to include AArch32 registers in cpu context save and restore
+# during world switch. This flag must be set to 0 for AArch64-only platforms.
+CTX_INCLUDE_AARCH32_REGS       := 1
 # Determine the version of ARM GIC architecture to use for interrupt management
 # in EL3. The platform port can change this value if needed.
 ARM_GIC_ARCH                   := 2
@@ -392,6 +395,7 @@ $(eval $(call assert_boolean,DEBUG))
 $(eval $(call assert_boolean,NS_TIMER_SWITCH))
 $(eval $(call assert_boolean,RESET_TO_BL31))
 $(eval $(call assert_boolean,CTX_INCLUDE_FPREGS))
+$(eval $(call assert_boolean,CTX_INCLUDE_AARCH32_REGS))
 $(eval $(call assert_boolean,ASM_ASSERTION))
 $(eval $(call assert_boolean,USE_COHERENT_MEM))
 $(eval $(call assert_boolean,DISABLE_PEDANTIC))
@@ -419,6 +423,7 @@ $(eval $(call add_define,SPD_${SPD}))
 $(eval $(call add_define,NS_TIMER_SWITCH))
 $(eval $(call add_define,RESET_TO_BL31))
 $(eval $(call add_define,CTX_INCLUDE_FPREGS))
+$(eval $(call add_define,CTX_INCLUDE_AARCH32_REGS))
 $(eval $(call add_define,ARM_GIC_ARCH))
 $(eval $(call add_define,ARM_CCI_PRODUCT_ID))
 $(eval $(call add_define,ASM_ASSERTION))
index bd40608bc789fdc79361796fe4898a69439c6262..972c7f68cd18aa746bf12284efee7a5c995d6eb2 100644 (file)
@@ -32,6 +32,7 @@
 #include <assert.h>
 #include <context.h>
 #include <context_mgmt.h>
+#include <debug.h>
 #include <platform.h>
 
 /*
@@ -66,6 +67,19 @@ void bl1_prepare_next_image(unsigned int image_id)
        image_desc_t *image_desc;
        entry_point_info_t *next_bl_ep;
 
+#if CTX_INCLUDE_AARCH32_REGS
+       /*
+        * Ensure that the build flag to save AArch32 system registers in CPU
+        * context is not set for AArch64-only platforms.
+        */
+       if (((read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL1_SHIFT)
+                       & ID_AA64PFR0_ELX_MASK) == 0x1) {
+               ERROR("EL1 supports AArch64-only. Please set build flag "
+                               "CTX_INCLUDE_AARCH32_REGS = 0");
+               panic();
+       }
+#endif
+
        /* Get the image descriptor. */
        image_desc = bl1_plat_get_image_desc(image_id);
        assert(image_desc);
index 835d41e87bbdc10818fafddf759a9a917916369f..7f04d2188ceb5a1b4fc0ae6b3fcc085248644c28 100644 (file)
@@ -145,6 +145,19 @@ void bl31_prepare_next_image_entry(void)
        entry_point_info_t *next_image_info;
        uint32_t image_type;
 
+#if CTX_INCLUDE_AARCH32_REGS
+       /*
+        * Ensure that the build flag to save AArch32 system registers in CPU
+        * context is not set for AArch64-only platforms.
+        */
+       if (((read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL1_SHIFT)
+                       & ID_AA64PFR0_ELX_MASK) == 0x1) {
+               ERROR("EL1 supports AArch64-only. Please set build flag "
+                               "CTX_INCLUDE_AARCH32_REGS = 0");
+               panic();
+       }
+#endif
+
        /* Determine which image to execute next */
        image_type = bl31_get_next_image_type();
 
index 0baa9b2f7c96f6f2c92c0b21b1d8a22f0a9a9b75..d51daa78c801f06b60154e2be36d62850cf025f6 100644 (file)
@@ -57,14 +57,6 @@ func el1_sysregs_context_save
        mrs     x10, elr_el1
        stp     x9, x10, [x0, #CTX_SPSR_EL1]
 
-       mrs     x11, spsr_abt
-       mrs     x12, spsr_und
-       stp     x11, x12, [x0, #CTX_SPSR_ABT]
-
-       mrs     x13, spsr_irq
-       mrs     x14, spsr_fiq
-       stp     x13, x14, [x0, #CTX_SPSR_IRQ]
-
        mrs     x15, sctlr_el1
        mrs     x16, actlr_el1
        stp     x15, x16, [x0, #CTX_SCTLR_EL1]
@@ -93,10 +85,6 @@ func el1_sysregs_context_save
        mrs     x10, tpidrro_el0
        stp     x9, x10, [x0, #CTX_TPIDR_EL0]
 
-       mrs     x11, dacr32_el2
-       mrs     x12, ifsr32_el2
-       stp     x11, x12, [x0, #CTX_DACR32_EL2]
-
        mrs     x13, par_el1
        mrs     x14, far_el1
        stp     x13, x14, [x0, #CTX_PAR_EL1]
@@ -109,6 +97,24 @@ func el1_sysregs_context_save
        mrs     x9, vbar_el1
        stp     x17, x9, [x0, #CTX_CONTEXTIDR_EL1]
 
+       /* Save AArch32 system registers if the build has instructed so */
+#if CTX_INCLUDE_AARCH32_REGS
+       mrs     x11, spsr_abt
+       mrs     x12, spsr_und
+       stp     x11, x12, [x0, #CTX_SPSR_ABT]
+
+       mrs     x13, spsr_irq
+       mrs     x14, spsr_fiq
+       stp     x13, x14, [x0, #CTX_SPSR_IRQ]
+
+       mrs     x15, dacr32_el2
+       mrs     x16, ifsr32_el2
+       stp     x15, x16, [x0, #CTX_DACR32_EL2]
+
+       mrs     x17, fpexc32_el2
+       str     x17, [x0, #CTX_FP_FPEXC32_EL2]
+#endif
+
        /* Save NS timer registers if the build has instructed so */
 #if NS_TIMER_SWITCH
        mrs     x10, cntp_ctl_el0
@@ -123,9 +129,6 @@ func el1_sysregs_context_save
        str     x14, [x0, #CTX_CNTKCTL_EL1]
 #endif
 
-       mrs     x15, fpexc32_el2
-       str     x15, [x0, #CTX_FP_FPEXC32_EL2]
-
        ret
 endfunc el1_sysregs_context_save
 
@@ -143,14 +146,6 @@ func el1_sysregs_context_restore
        msr     spsr_el1, x9
        msr     elr_el1, x10
 
-       ldp     x11, x12, [x0, #CTX_SPSR_ABT]
-       msr     spsr_abt, x11
-       msr     spsr_und, x12
-
-       ldp     x13, x14, [x0, #CTX_SPSR_IRQ]
-       msr     spsr_irq, x13
-       msr     spsr_fiq, x14
-
        ldp     x15, x16, [x0, #CTX_SCTLR_EL1]
        msr     sctlr_el1, x15
        msr     actlr_el1, x16
@@ -179,10 +174,6 @@ func el1_sysregs_context_restore
        msr     tpidr_el0, x9
        msr     tpidrro_el0, x10
 
-       ldp     x11, x12, [x0, #CTX_DACR32_EL2]
-       msr     dacr32_el2, x11
-       msr     ifsr32_el2, x12
-
        ldp     x13, x14, [x0, #CTX_PAR_EL1]
        msr     par_el1, x13
        msr     far_el1, x14
@@ -195,6 +186,23 @@ func el1_sysregs_context_restore
        msr     contextidr_el1, x17
        msr     vbar_el1, x9
 
+       /* Restore AArch32 system registers if the build has instructed so */
+#if CTX_INCLUDE_AARCH32_REGS
+       ldp     x11, x12, [x0, #CTX_SPSR_ABT]
+       msr     spsr_abt, x11
+       msr     spsr_und, x12
+
+       ldp     x13, x14, [x0, #CTX_SPSR_IRQ]
+       msr     spsr_irq, x13
+       msr     spsr_fiq, x14
+
+       ldp     x15, x16, [x0, #CTX_DACR32_EL2]
+       msr     dacr32_el2, x15
+       msr     ifsr32_el2, x16
+
+       ldr     x17, [x0, #CTX_FP_FPEXC32_EL2]
+       msr     fpexc32_el2, x17
+#endif
        /* Restore NS timer registers if the build has instructed so */
 #if NS_TIMER_SWITCH
        ldp     x10, x11, [x0, #CTX_CNTP_CTL_EL0]
@@ -209,11 +217,7 @@ func el1_sysregs_context_restore
        msr     cntkctl_el1, x14
 #endif
 
-       ldr     x15, [x0, #CTX_FP_FPEXC32_EL2]
-       msr     fpexc32_el2, x15
-
        /* No explict ISB required here as ERET covers it */
-
        ret
 endfunc el1_sysregs_context_restore
 
index cd9c8c33e1af5e9281274a734168c3c723e76d64..0911eb8bef74bac957a58c6dfe955a35419d544e 100644 (file)
@@ -380,6 +380,12 @@ performed.
     any register that is not part of the SBSA generic UART specification.
     Default value is 0 (a full PL011 compliant UART is present).
 
+*   `CTX_INCLUDE_AARCH32_REGS` : Boolean option that, when set to 1, will cause
+    the AArch32 system registers to be included when saving and restoring the
+    CPU context. The option must be set to 0 for AArch64-only platforms (that
+    is on hardware that does not implement AArch32, or at least not at EL1 and
+    higher ELs). Default value is 1.
+
 *   `CTX_INCLUDE_FPREGS`: Boolean option that, when set to 1, will cause the FP
     registers to be included when saving and restoring the CPU context. Default
     is 0.
index 0dfebe0bbcc8056c0da90684064fae6ae8fb7718..ec47f2ad8d7a4687c4eb6dcd85076c621c8e3ae3 100644 (file)
 #define CTX_SYSREGS_OFFSET     (CTX_EL3STATE_OFFSET + CTX_EL3STATE_END)
 #define CTX_SPSR_EL1           0x0
 #define CTX_ELR_EL1            0x8
-#define CTX_SPSR_ABT           0x10
-#define CTX_SPSR_UND           0x18
-#define CTX_SPSR_IRQ           0x20
-#define CTX_SPSR_FIQ           0x28
-#define CTX_SCTLR_EL1          0x30
-#define CTX_ACTLR_EL1          0x38
-#define CTX_CPACR_EL1          0x40
-#define CTX_CSSELR_EL1         0x48
-#define CTX_SP_EL1             0x50
-#define CTX_ESR_EL1            0x58
-#define CTX_TTBR0_EL1          0x60
-#define CTX_TTBR1_EL1          0x68
-#define CTX_MAIR_EL1           0x70
-#define CTX_AMAIR_EL1          0x78
-#define CTX_TCR_EL1            0x80
-#define CTX_TPIDR_EL1          0x88
-#define CTX_TPIDR_EL0          0x90
-#define CTX_TPIDRRO_EL0                0x98
-#define CTX_DACR32_EL2         0xa0
-#define CTX_IFSR32_EL2         0xa8
-#define CTX_PAR_EL1            0xb0
-#define CTX_FAR_EL1            0xb8
-#define CTX_AFSR0_EL1          0xc0
-#define CTX_AFSR1_EL1          0xc8
-#define CTX_CONTEXTIDR_EL1     0xd0
-#define CTX_VBAR_EL1           0xd8
+#define CTX_SCTLR_EL1          0x10
+#define CTX_ACTLR_EL1          0x18
+#define CTX_CPACR_EL1          0x20
+#define CTX_CSSELR_EL1         0x28
+#define CTX_SP_EL1             0x30
+#define CTX_ESR_EL1            0x38
+#define CTX_TTBR0_EL1          0x40
+#define CTX_TTBR1_EL1          0x48
+#define CTX_MAIR_EL1           0x50
+#define CTX_AMAIR_EL1          0x58
+#define CTX_TCR_EL1            0x60
+#define CTX_TPIDR_EL1          0x68
+#define CTX_TPIDR_EL0          0x70
+#define CTX_TPIDRRO_EL0                0x78
+#define CTX_PAR_EL1            0x80
+#define CTX_FAR_EL1            0x88
+#define CTX_AFSR0_EL1          0x90
+#define CTX_AFSR1_EL1          0x98
+#define CTX_CONTEXTIDR_EL1     0xa0
+#define CTX_VBAR_EL1           0xa8
+
+/*
+ * If the platform is AArch64-only, there is no need to save and restore these
+ * AArch32 registers.
+ */
+#if CTX_INCLUDE_AARCH32_REGS
+#define CTX_SPSR_ABT           0xb0
+#define CTX_SPSR_UND           0xb8
+#define CTX_SPSR_IRQ           0xc0
+#define CTX_SPSR_FIQ           0xc8
+#define CTX_DACR32_EL2         0xd0
+#define CTX_IFSR32_EL2         0xd8
+#define CTX_FP_FPEXC32_EL2     0xe0
+#define CTX_TIMER_SYSREGS_OFF          0xf0 /* Align to the next 16 byte boundary */
+#else
+#define CTX_TIMER_SYSREGS_OFF          0xb0
+#endif /* __CTX_INCLUDE_AARCH32_REGS__ */
+
 /*
  * If the timer registers aren't saved and restored, we don't have to reserve
  * space for them in the context
  */
 #if NS_TIMER_SWITCH
-#define CTX_CNTP_CTL_EL0       0xe0
-#define CTX_CNTP_CVAL_EL0      0xe8
-#define CTX_CNTV_CTL_EL0       0xf0
-#define CTX_CNTV_CVAL_EL0      0xf8
-#define CTX_CNTKCTL_EL1                0x100
-#define CTX_FP_FPEXC32_EL2     0x108
-#define CTX_SYSREGS_END                0x110
+#define CTX_CNTP_CTL_EL0       (CTX_TIMER_SYSREGS_OFF + 0x0)
+#define CTX_CNTP_CVAL_EL0      (CTX_TIMER_SYSREGS_OFF + 0x8)
+#define CTX_CNTV_CTL_EL0       (CTX_TIMER_SYSREGS_OFF + 0x10)
+#define CTX_CNTV_CVAL_EL0      (CTX_TIMER_SYSREGS_OFF + 0x18)
+#define CTX_CNTKCTL_EL1                (CTX_TIMER_SYSREGS_OFF + 0x20)
+#define CTX_SYSREGS_END                (CTX_TIMER_SYSREGS_OFF + 0x30) /* Align to the next 16 byte boundary */
 #else
-#define CTX_FP_FPEXC32_EL2     0xe0
-#define CTX_SYSREGS_END                0xf0
-#endif
+#define CTX_SYSREGS_END                CTX_TIMER_SYSREGS_OFF
+#endif /* __NS_TIMER_SWITCH__ */
 
 /*******************************************************************************
  * Constants that allow assembler code to access members of and the 'fp_regs'